<html>
  <head>
    <script src="../../dist/ohm.min.js"></script>
    <script id="ohmGrammar" type="text/ohm-js">

Ohm {

  Grammars
    = Grammar*

  Grammar
    = ident SuperGrammar? "{" Rule* "}"

  SuperGrammar
    = "<:" ident

  Rule
    = ident Formals? ruleDescr? "="  RuleBody  -- define
    | ident Formals?            ":=" RuleBody  -- override
    | ident Formals?            "+=" RuleBody  -- extend

  RuleBody
    = "|"? NonemptyListOf<TopLevelTerm, "|">

  TopLevelTerm
    = Seq caseName  -- inline
    | Seq

  Formals
    = "<" ListOf<ident, ","> ">"

  Params
    = "<" ListOf<Seq, ","> ">"

  Alt
    = NonemptyListOf<Seq, "|">

  Seq
    = Iter*

  Iter
    = Pred "*"  -- star
    | Pred "+"  -- plus
    | Pred "?"  -- opt
    | Pred

  Pred
    = "~" Lex  -- not
    | "&" Lex  -- lookahead
    | Lex

  Lex
    = "#" Base  -- lex
    | Base

  Base
    = ident Params? ~(ruleDescr? "=" | ":=" | "+=")  -- application
    | terminal ".." terminal                         -- range
    | terminal                                       -- terminal
    | "(" Alt ")"                                    -- paren

  ruleDescr  (a rule description)
    = "(" ruleDescrText ")"

  ruleDescrText
    = (~")" any)*

  caseName
    = "--" (~"\n" space)* name (~"\n" space)* ("\n" | &"}")

  name  (a name)
    = nameFirst nameRest*

  nameFirst
    = "_"
    | letter

  nameRest
    = "_"
    | alnum

  ident  (an identifier)
    = name

  terminal
    = "\"" terminalChar* "\""

  terminalChar
    = escapeChar
    | ~"\\" ~"\"" ~"\n" any

  escapeChar  (an escape sequence)
    = "\\\\"                                     -- backslash
    | "\\\""                                     -- doubleQuote
    | "\\\'"                                     -- singleQuote
    | "\\b"                                      -- backspace
    | "\\n"                                      -- lineFeed
    | "\\r"                                      -- carriageReturn
    | "\\t"                                      -- tab
    | "\\u" hexDigit hexDigit hexDigit hexDigit  -- unicodeEscape
    | "\\x" hexDigit hexDigit                    -- hexEscape

  space
   += comment

  comment
    = "//" (~"\n" any)* "\n"  -- singleLine
    | "/*" (~"*/" any)* "*/"  -- multiLine

  tokens = token*

  token = caseName | comment | ident | operator | punctuation | terminal | any

  operator = "<:" | "=" | ":=" | "+=" | "*" | "+" | "?" | "~" | "&"

  punctuation = "<" | ">" | "," | "--"
}

    </script>
    <script id="es5grammar" type="just data">

/*
  This grammar was originally based on Tom Van Cutsem's ES5 parser from the
  es-lab project (https://github.com/tvcutsem/es-lab/blob/master/src/parser/es5parser.ojs),
  and was adapted to Ohm by Tony Garnock-Jones <tonygarnockjones@gmail.com> in 2014.

  The original copyright and license follows:
*/

// Copyright (C) 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* (end of original copyright and license) */

ES5 {

  Program = &(Directive*) SourceElement*

  // §A.1 Lexical Grammar -- http://ecma-international.org/ecma-262/5.1/#sec-A.1

  /*
    Note: the following lexical conventions (see http://ecma-international.org/ecma-262/5.1/#sec-7)
    are not implemented in this parser.

    // Goal production in contexts where a leading "/" or "/=" is permitted:
    InputElementDiv = whitespace | lineTerminator | comment | token | DivPunctuator

    // Goal production in contexts where a leading "/" or "/=' is not permitted:
    InputElementRegExp = whitespace | lineTerminator | comment | token | regularExpressionLiteral
  */

  sourceCharacter = any

  // Override Ohm's built-in definition of space.
  space := whitespace | lineTerminator | comment

  whitespace = "\t"
             | "\x0B"    -- verticalTab
             | "\x0C"    -- formFeed
             | " "
             | "\u00A0"  -- noBreakSpace
             | "\uFEFF"  -- byteOrderMark
             | unicodeSpaceSeparator

  lineTerminator = "\n" | "\r" | "\u2028" | "\u2029"
  lineTerminatorSequence = "\n" | "\r" ~"\n" | "\u2028" | "\u2029" | "\r\n"

  comment = multiLineComment | singleLineComment

  multiLineComment = "/*" (~"*/" sourceCharacter)* "*/"
  singleLineComment = "//" (~lineTerminator sourceCharacter)*

  identifier (an identifier) = ~reservedWord identifierName
  identifierName = identifierStart identifierPart*

  identifierStart = letter | "$" | "_"
                  | "\\" unicodeEscapeSequence -- escaped
  identifierPart = identifierStart | unicodeCombiningMark
                 | unicodeDigit | unicodeConnectorPunctuation
                 | "\u200C" | "\u200D"
 letter += unicodeCategoryNl
  unicodeCategoryNl
    = "\u2160".."\u2182" | "\u3007" | "\u3021".."\u3029"
  unicodeDigit (a digit)
    = "\u0030".."\u0039" | "\u0660".."\u0669" | "\u06F0".."\u06F9" | "\u0966".."\u096F" | "\u09E6".."\u09EF" | "\u0A66".."\u0A6F" | "\u0AE6".."\u0AEF" | "\u0B66".."\u0B6F" | "\u0BE7".."\u0BEF" | "\u0C66".."\u0C6F" | "\u0CE6".."\u0CEF" | "\u0D66".."\u0D6F" | "\u0E50".."\u0E59" | "\u0ED0".."\u0ED9" | "\u0F20".."\u0F29" | "\uFF10".."\uFF19"

  unicodeCombiningMark (a Unicode combining mark)
    = "\u0300".."\u0345" | "\u0360".."\u0361" | "\u0483".."\u0486" | "\u0591".."\u05A1" | "\u05A3".."\u05B9" | "\u05BB".."\u05BD" | "\u05BF".."\u05BF" | "\u05C1".."\u05C2" | "\u05C4".."\u05C4" | "\u064B".."\u0652" | "\u0670".."\u0670" | "\u06D6".."\u06DC" | "\u06DF".."\u06E4" | "\u06E7".."\u06E8" | "\u06EA".."\u06ED" | "\u0901".."\u0902" | "\u093C".."\u093C" | "\u0941".."\u0948" | "\u094D".."\u094D" | "\u0951".."\u0954" | "\u0962".."\u0963" | "\u0981".."\u0981" | "\u09BC".."\u09BC" | "\u09C1".."\u09C4" | "\u09CD".."\u09CD" | "\u09E2".."\u09E3" | "\u0A02".."\u0A02" | "\u0A3C".."\u0A3C" | "\u0A41".."\u0A42" | "\u0A47".."\u0A48" | "\u0A4B".."\u0A4D" | "\u0A70".."\u0A71" | "\u0A81".."\u0A82" | "\u0ABC".."\u0ABC" | "\u0AC1".."\u0AC5" | "\u0AC7".."\u0AC8" | "\u0ACD".."\u0ACD" | "\u0B01".."\u0B01" | "\u0B3C".."\u0B3C" | "\u0B3F".."\u0B3F" | "\u0B41".."\u0B43" | "\u0B4D".."\u0B4D" | "\u0B56".."\u0B56" | "\u0B82".."\u0B82" | "\u0BC0".."\u0BC0" | "\u0BCD".."\u0BCD" | "\u0C3E".."\u0C40" | "\u0C46".."\u0C48" | "\u0C4A".."\u0C4D" | "\u0C55".."\u0C56" | "\u0CBF".."\u0CBF" | "\u0CC6".."\u0CC6" | "\u0CCC".."\u0CCD" | "\u0D41".."\u0D43" | "\u0D4D".."\u0D4D" | "\u0E31".."\u0E31" | "\u0E34".."\u0E3A" | "\u0E47".."\u0E4E" | "\u0EB1".."\u0EB1" | "\u0EB4".."\u0EB9" | "\u0EBB".."\u0EBC" | "\u0EC8".."\u0ECD" | "\u0F18".."\u0F19" | "\u0F35".."\u0F35" | "\u0F37".."\u0F37" | "\u0F39".."\u0F39" | "\u0F71".."\u0F7E" | "\u0F80".."\u0F84" | "\u0F86".."\u0F87" | "\u0F90".."\u0F95" | "\u0F97".."\u0F97" | "\u0F99".."\u0FAD" | "\u0FB1".."\u0FB7" | "\u0FB9".."\u0FB9" | "\u20D0".."\u20DC" | "\u20E1".."\u20E1" | "\u302A".."\u302F" | "\u3099".."\u309A" | "\uFB1E".."\uFB1E" | "\uFE20".."\uFE23"

  unicodeConnectorPunctuation = "\u005F" | "\u203F".."\u2040" | "\u30FB" | "\uFE33".."\uFE34" | "\uFE4D".."\uFE4F" | "\uFF3F" | "\uFF65"
  unicodeSpaceSeparator = "\u2000".."\u200B" | "\u3000"

  reservedWord = keyword | futureReservedWord | nullLiteral | booleanLiteral

  // Note: keywords that are the complete prefix of another keyword should
  // be prioritized (e.g. 'in' should come before 'instanceof')
  keyword = break    | do        | instanceof | typeof
          | case     | else      | new        | var
          | catch    | finally   | return     | void
          | continue | for       | switch     | while
          | debugger | function  | this       | with
          | default  | if        | throw
          | delete   | in        | try

  futureReservedWordLax = class  | enum  | extends
                        | super  | const | export
                        | import

  futureReservedWordStrict = futureReservedWordLax
                           | implements | let     | private   | public
                           | interface  | package | protected | static
                           | yield

  futureReservedWord = futureReservedWordStrict

  /*
    Note: Punctuator and DivPunctuator (see https://es5.github.io/x7.html#x7.7) are
    not currently used by this grammar.
  */

  literal = nullLiteral | booleanLiteral | numericLiteral
          | stringLiteral | regularExpressionLiteral // spec forgot Regexp literals in appendix?
  nullLiteral = "null" ~identifierPart
  booleanLiteral = ("true" | "false") ~identifierPart

  // For semantics on how decimal literals are constructed, see section 7.8.3

  // Note that the ordering of hexIntegerLiteral and decimalLiteral is reversed w.r.t. the spec
  // This is intentional: the order decimalLiteral | hexIntegerLiteral will parse
  // "0x..." as a decimal literal "0" followed by "x..."
  numericLiteral = octalIntegerLiteral | hexIntegerLiteral | decimalLiteral

  decimalLiteral = decimalIntegerLiteral "." decimalDigit* exponentPart -- bothParts
                 |                       "." decimalDigit+ exponentPart -- decimalsOnly
                 | decimalIntegerLiteral                   exponentPart -- integerOnly

  decimalIntegerLiteral = nonZeroDigit decimalDigit*  -- nonZero
                        | "0"                         -- zero
  decimalDigit = "0".."9"
  nonZeroDigit = "1".."9"

  exponentPart = exponentIndicator signedInteger -- present
               |                                 -- absent
  exponentIndicator = "e" | "E"
  signedInteger = "+" decimalDigit* -- positive
                | "-" decimalDigit* -- negative
                |     decimalDigit+ -- noSign

  hexIntegerLiteral = "0x" hexDigit+
                    | "0X" hexDigit+

  // hexDigit defined in Ohm's built-in rules (otherwise: hexDigit = "0".."9" | "a".."f" | "A".."F")

  octalIntegerLiteral = "0" octalDigit+

  octalDigit = "0".."7"

  // For semantics on how string literals are constructed, see section 7.8.4
  stringLiteral = "\"" doubleStringCharacter* "\""
                | "'" singleStringCharacter* "'"
  doubleStringCharacter = ~("\"" | "\\" | lineTerminator) sourceCharacter -- nonEscaped
                        | "\\" escapeSequence                             -- escaped
                        | lineContinuation                                -- lineContinuation
  singleStringCharacter = ~("'" | "\\" | lineTerminator) sourceCharacter -- nonEscaped
                        | "\\" escapeSequence                            -- escaped
                        | lineContinuation                               -- lineContinuation
  lineContinuation = "\\" lineTerminatorSequence
  escapeSequence = unicodeEscapeSequence
                 | hexEscapeSequence
                 | octalEscapeSequence
                 | characterEscapeSequence  // Must come last.
  characterEscapeSequence = singleEscapeCharacter
                          | nonEscapeCharacter
  singleEscapeCharacter = "'" | "\"" | "\\" | "b" | "f" | "n" | "r" | "t" | "v"
  nonEscapeCharacter = ~(escapeCharacter | lineTerminator) sourceCharacter
  escapeCharacter = singleEscapeCharacter | decimalDigit | "x" | "u"
  octalEscapeSequence = zeroToThree octalDigit octalDigit    -- whole
                      | fourToSeven octalDigit               -- eightTimesfourToSeven
                      | zeroToThree octalDigit ~decimalDigit -- eightTimesZeroToThree
                      | octalDigit ~decimalDigit             -- octal
  hexEscapeSequence = "x" hexDigit hexDigit
  unicodeEscapeSequence = "u" hexDigit hexDigit hexDigit hexDigit

  zeroToThree = "0".."3"
  fourToSeven = "4".."7"

  // §7.8.5 Regular Expression Literals -- http://ecma-international.org/ecma-262/5.1/#sec-7.8.5

  regularExpressionLiteral = "/" regularExpressionBody "/" regularExpressionFlags
  regularExpressionBody = regularExpressionFirstChar regularExpressionChar*
  regularExpressionFirstChar = ~("*" | "\\" | "/" | "[") regularExpressionNonTerminator
                             | regularExpressionBackslashSequence
                             | regularExpressionClass
  regularExpressionChar = ~("\\" | "/" | "[") regularExpressionNonTerminator
                        | regularExpressionBackslashSequence
                        | regularExpressionClass
  regularExpressionBackslashSequence = "\\" regularExpressionNonTerminator
  regularExpressionNonTerminator = ~(lineTerminator) sourceCharacter
  regularExpressionClass = "[" regularExpressionClassChar* "]"
  regularExpressionClassChar = ~("]" | "\\") regularExpressionNonTerminator
                             | regularExpressionBackslashSequence
  regularExpressionFlags = identifierPart*

  // === Implementation-level rules (not part of the spec) ===

  multiLineCommentNoNL = "/*" (~("*/" | lineTerminator) sourceCharacter)* "*/"

  // does not accept lineTerminators, not even implicit ones in a multiLineComment (cf. section 7.4)
  spacesNoNL = (whitespace | singleLineComment | multiLineCommentNoNL)*

  // A semicolon is "automatically inserted" if a newline or the end of the input stream is
  // reached, or the offending token is "}".
  // See http://ecma-international.org/ecma-262/5.1/#sec-7.9 for more information.
  // NOTE: Applications of this rule *must* appear in a lexical context -- either in the body of a
  // lexical rule, or inside `#()`.
  sc = space* (";" | end)
     | spacesNoNL (lineTerminator | ~multiLineCommentNoNL multiLineComment | &"}")

  // Convenience rules for parsing keyword tokens.
  break = "break" ~identifierPart
  do = "do" ~identifierPart
  instanceof = "instanceof" ~identifierPart
  typeof = "typeof" ~identifierPart
  case = "case" ~identifierPart
  else = "else" ~identifierPart
  new = "new" ~identifierPart
  var = "var" ~identifierPart
  catch = "catch" ~identifierPart
  finally = "finally" ~identifierPart
  return = "return" ~identifierPart
  void = "void" ~identifierPart
  continue = "continue" ~identifierPart
  for = "for" ~identifierPart
  switch = "switch" ~identifierPart
  while = "while" ~identifierPart
  debugger = "debugger" ~identifierPart
  function = "function" ~identifierPart
  this = "this" ~identifierPart
  with = "with" ~identifierPart
  default = "default" ~identifierPart
  if = "if" ~identifierPart
  throw = "throw" ~identifierPart
  delete = "delete" ~identifierPart
  in = "in" ~identifierPart
  try = "try" ~identifierPart
  get = "get" ~identifierPart
  set = "set" ~identifierPart
  class = "class" ~identifierPart
  enum = "enum" ~identifierPart
  extends = "extends" ~identifierPart
  super = "super" ~identifierPart
  const = "const" ~identifierPart
  export = "export" ~identifierPart
  import = "import" ~identifierPart
  implements = "implements" ~identifierPart
  let = "let" ~identifierPart
  private = "private" ~identifierPart
  public = "public" ~identifierPart
  interface = "interface" ~identifierPart
  package = "package" ~identifierPart
  protected = "protected" ~identifierPart
  static = "static" ~identifierPart
  yield = "yield" ~identifierPart
  
  // end of lexical rules

  noIn = ~in
  withIn =

  // §A.3 Expressions -- http://ecma-international.org/ecma-262/5.1/#sec-A.3

  PrimaryExpression = this
                    | identifier
                    | literal
                      // ( litToken.type === "regexp"
                      //   ? this.ast(_fromIdx, "RegExpExpr",{body:  litToken.value.body
                      //                            flags: litToken.value.flags}, [])
                      //   : this.ast(_fromIdx, "LiteralExpr",{type:  litToken.type
                      //                             value: litToken.value}, []) )
                    | ArrayLiteral
                    | ObjectLiteral
                    | "(" Expression<withIn> ")"  -- parenExpr

  ArrayLiteral = "[" ListOf<AssignmentExpressionOrElision, ","> "]"
  AssignmentExpressionOrElision = AssignmentExpression<withIn>
                                |                       -- elision

  ObjectLiteral = "{" ListOf<PropertyAssignment, ","> "}"              -- noTrailingComma
                | "{" NonemptyListOf<PropertyAssignment, ","> "," "}"  -- trailingComma

  PropertyAssignment = get PropertyName "(" ")" "{" FunctionBody "}"                  -- getter
                     | set PropertyName "(" FormalParameter ")" "{" FunctionBody "}"  -- setter
                     | PropertyName ":" AssignmentExpression<withIn>                  -- simple

  PropertyName = identifierName
               | stringLiteral
               | numericLiteral

  MemberExpression = MemberExpression "[" Expression<withIn> "]"  -- arrayRefExp
                   | MemberExpression "." identifierName  -- propRefExp
                   | new MemberExpression Arguments       -- newExp
                   | FunctionExpression
                   | PrimaryExpression

  NewExpression = MemberExpression
                | new NewExpression -- newExp

  CallExpression = CallExpression "[" Expression<withIn> "]"  -- arrayRefExp
                 | CallExpression "." identifierName  -- propRefExp
                 | CallExpression Arguments           -- callExpExp
                 | MemberExpression Arguments         -- memberExpExp

  Arguments = "(" ListOf<AssignmentExpression<withIn>, ","> ")"

  LeftHandSideExpression = CallExpression
                         | NewExpression

  PostfixExpression = LeftHandSideExpression #(spacesNoNL "++")  -- postIncrement
                    | LeftHandSideExpression #(spacesNoNL "--")  -- postDecrement
                    | LeftHandSideExpression

  UnaryExpression = delete UnaryExpression  -- deleteExp
                  | void   UnaryExpression  -- voidExp
                  | typeof UnaryExpression  -- typeofExp
                  | "++"   UnaryExpression  -- preIncrement
                  | "--"   UnaryExpression  -- preDecrement
                  | "+"    UnaryExpression  -- unaryPlus
                  | "-"    UnaryExpression  -- unaryMinus
                  | "~"    UnaryExpression  -- bnot
                  | "!"    UnaryExpression  -- lnot
                  | PostfixExpression

  MultiplicativeExpression = MultiplicativeExpression "*" UnaryExpression -- mul
                           | MultiplicativeExpression "/" UnaryExpression -- div
                           | MultiplicativeExpression "%" UnaryExpression -- mod
                           | UnaryExpression

  AdditiveExpression = AdditiveExpression "+" MultiplicativeExpression -- add
                     | AdditiveExpression "-" MultiplicativeExpression -- sub
                     | MultiplicativeExpression

  ShiftExpression = ShiftExpression "<<" AdditiveExpression  -- lsl
                  | ShiftExpression ">>>" AdditiveExpression -- lsr
                  | ShiftExpression ">>" AdditiveExpression  -- asr
                  | AdditiveExpression

  RelationalExpression<guardIn>
    = RelationalExpression<guardIn> "<" ShiftExpression           -- lt
    | RelationalExpression<guardIn> ">" ShiftExpression           -- gt
    | RelationalExpression<guardIn> "<=" ShiftExpression          -- le
    | RelationalExpression<guardIn> ">=" ShiftExpression          -- ge
    | RelationalExpression<guardIn> "instanceof" ShiftExpression  -- instanceOfExp
    | RelationalExpression<guardIn> guardIn "in" ShiftExpression  -- inExp
    | ShiftExpression

  EqualityExpression<guardIn>
    = EqualityExpression<guardIn> "==" RelationalExpression<guardIn>  -- equal
    | EqualityExpression<guardIn> "!=" RelationalExpression<guardIn>  -- notEqual
    | EqualityExpression<guardIn> "===" RelationalExpression<guardIn> -- eq
    | EqualityExpression<guardIn> "!==" RelationalExpression<guardIn> -- notEq
    | RelationalExpression<guardIn>

  BitwiseANDExpression<guardIn>
    = BitwiseANDExpression<guardIn> "&" EqualityExpression<guardIn> -- band
    | EqualityExpression<guardIn>

  BitwiseXORExpression<guardIn>
    = BitwiseXORExpression<guardIn> "^" BitwiseANDExpression<guardIn> -- bxor
    | BitwiseANDExpression<guardIn>

  BitwiseORExpression<guardIn>
    = BitwiseORExpression<guardIn> "|" BitwiseXORExpression<guardIn> -- bor
    | BitwiseXORExpression<guardIn>

  LogicalANDExpression<guardIn>
    = LogicalANDExpression<guardIn> "&&" BitwiseORExpression<guardIn> -- land
    | BitwiseORExpression<guardIn>

  LogicalORExpression<guardIn>
    = LogicalORExpression<guardIn> "||" LogicalANDExpression<guardIn> -- lor
    | LogicalANDExpression<guardIn>

  ConditionalExpression<guardIn>
    = LogicalORExpression<guardIn> "?" AssignmentExpression<withIn> ":" AssignmentExpression<guardIn> -- conditional
    | LogicalORExpression<guardIn>

  AssignmentExpression<guardIn>
    = LeftHandSideExpression assignmentOperator AssignmentExpression<guardIn> -- assignment
    | ConditionalExpression<guardIn>

  Expression<guardIn> (an expression)
    = Expression<guardIn> "," AssignmentExpression<guardIn> -- commaExp
    | AssignmentExpression<guardIn>

  assignmentOperator = "=" | ">>>=" | "<<=" | ">>="
                     | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|="

  // §A.4 Statements -- http://ecma-international.org/ecma-262/5.1/#sec-A.4

  Statement
    = Block
    | VariableStatement
    | EmptyStatement
    | ExpressionStatement
    | IfStatement
    | IterationStatement
    | ContinueStatement
    | BreakStatement
    | ReturnStatement
    | WithStatement
    | LabelledStatement
    | SwitchStatement
    | ThrowStatement
    | TryStatement
    | DebuggerStatement

  Block = "{" StatementList "}"

  StatementList = Statement*

  VariableStatement = var VariableDeclarationList<withIn> #sc

  VariableDeclarationList<guardIn> = NonemptyListOf<VariableDeclaration<guardIn>, ",">

  VariableDeclaration<guardIn> = identifier Initialiser<guardIn>?

  Initialiser<guardIn> = "=" AssignmentExpression<guardIn>

  EmptyStatement = ";" // note: this semicolon eats newlines

  ExpressionStatement = ~("{" | function) Expression<withIn> #sc

  IfStatement = if "(" Expression<withIn> ")" Statement (else Statement)?

  IterationStatement = do Statement while "(" Expression<withIn> ")" #sc  -- doWhile
                     | while "(" Expression<withIn> ")" Statement           -- whileDo
                     | for "(" Expression<noIn>? ";"
                                 Expression<withIn>? ";"
                                 Expression<withIn>? ")" Statement          -- for3
                     | for "(" var VariableDeclarationList<noIn> ";"
                                 Expression<withIn>? ";"
                                 Expression<withIn>? ")" Statement          -- for3var
                     | for "(" LeftHandSideExpression in
                                 Expression<withIn> ")" Statement           -- forIn
                     | for "(" var VariableDeclaration<noIn> in
                                 Expression<withIn> ")" Statement           -- forInVar

  ContinueStatement = continue #((spacesNoNL identifier)? sc)

  BreakStatement = break #((spacesNoNL identifier)? sc)

  ReturnStatement = return (#(spacesNoNL ~space) Expression<withIn>)? #sc

  WithStatement = with "(" Expression<withIn> ")" Statement

  SwitchStatement = switch "(" Expression<withIn> ")" CaseBlock

  CaseBlock = "{" CaseClause* DefaultClause CaseClause* "}"  -- withDefault
            | "{"                           CaseClause* "}"  -- withoutDefault

  CaseClause = case Expression<withIn> ":" Statement*

  DefaultClause = default ":" Statement*

  LabelledStatement = identifier ":" Statement

  ThrowStatement = throw Expression<withIn> #sc  -- throwExpr

  TryStatement = try Block Catch Finally  -- tryCatchFinally
               | try Block Finally        -- tryFinally
               | try Block Catch          -- tryCatch

  Catch = catch "(" FormalParameter ")" Block

  Finally = finally Block

  DebuggerStatement = #(debugger sc)

  // §A.5 Functions and Programs -- http://ecma-international.org/ecma-262/5.1/#sec-A.5

  FunctionDeclaration
    = function identifier "(" FormalParameterList ")" "{" FunctionBody "}"

  FunctionExpression
    = function identifier "(" FormalParameterList ")" "{" FunctionBody "}"  -- named
    | function "(" FormalParameterList ")" "{" FunctionBody "}"             -- anonymous

  FormalParameterList = ListOf<FormalParameter, ",">

  FormalParameter = identifier

  FunctionBody = &(Directive*) SourceElement*

  SourceElement = Declaration | Statement

  // Broken out so es6 can override to include ConstDecl and LetDecl
  Declaration = FunctionDeclaration

  Directive = stringLiteral #sc
}

ES5Lax <: ES5 {
  futureReservedWord := futureReservedWordLax
}

    </script>
  </head>
  <body>
    (see console output)
    <script id="myScript">

var program = es5grammar.text;

function time(fn) {
  var startTime = Date.now();
  fn();
  var endTime = Date.now();
  return endTime - startTime;
}

var g = ohm.grammarFromScriptElement();

function assert(cond) {
  if (!cond) {
    throw new Error('failed assertion');
  }
}

var newRule = 'Foo = Bar Baz*\n';
var program2 = program.substring(0, 1644) + newRule + program.substring(1644);

var newComment = '/* hello world, this is a test */\n';
var program3 = newComment + program2;

var program4 = program2 + newComment;

var nonIncrementalTime = 0;
var incrementalReplaceTime = 0;
var incrementalMatchTime = 0;
var incrMatcher = g.matcher();

var editNumber = 0;
function makeChange(idx1, idx2, str, expectedStr) {
  editNumber++;

  incrementalReplaceTime += time(() => { incrMatcher.replaceInputRange(idx1, idx2, str); });
  assert(incrMatcher.getInput() === expectedStr);

  var mr;
  incrementalMatchTime += time(() => { mr = incrMatcher.match(); });
  assert(mr.succeeded());
  
  nonIncrementalTime += time(() => g.match(expectedStr));
  assert(mr.succeeded());

  showStats();
}

function showStats() {
  console.log('[edit #' + editNumber + ']');
  console.log('  cummulative stats:');
  console.log('    non-incremental =', nonIncrementalTime);
  console.log(
      '    incremental =', incrementalReplaceTime + incrementalMatchTime, '=',
      incrementalReplaceTime, 'replaceInputRange +',
      incrementalMatchTime, 'match\n');
}

makeChange(0, 0, program, program);
makeChange(1644, 1644, newRule, program2);
makeChange(0, 0, newComment, program3);
makeChange(0, newComment.length, '', program2);
makeChange(program2.length, program2.length, newComment, program4);

console.log('speedup', nonIncrementalTime / (incrementalReplaceTime + incrementalMatchTime));

    </script>
  </body>
</html>

